#pragma once
#include "math.h"
#include "graphics.h"


class IStackAllocator;
class IVertex2;
class ILinearEdge2;

/** @brief simplex of 2-dimensional space. */
class Simplex2
{
public:
	virtual ~Simplex2() {}
	/* @todo rename to internalPoint, startVertex, endVertex */
	virtual const Vector2 internalPoint() const = 0;
	virtual const Vector2 startPoint() const = 0;
	virtual const Vector2 endPoint() const = 0;

	const Vector2 startNormal() const;
	const Vector2 endNormal() const;
	
	const Vector2 edgeTangent() const
	{
		Vector2 tangent(endPoint() - startPoint());
		tangent.normalize();
		return tangent;
	}

	const Vector2 edgeNormal() const
	{
		const Vector2 tan = edgeTangent();
		return Vector2(tan.y(), - tan.x());
	}


	//dynamic allocation API for IBoundary2
	ILinearEdge2* edge(IStackAllocator& alloc) const;
};

/** this can traverse all the simplices of their composed shape counter-clockwise. */
class ISimplexIterator2
{
public:
	virtual ~ISimplexIterator2() {}
	virtual const Simplex2& current() const = 0;
	virtual bool next() = 0;
};

/** @brief  this can be used as '1st' parameter for minkowski sum generation algorithm.
 *	this must be decomposed to simplex.
 */
class ISimplexDecomposed2
{
public:
	virtual ~ISimplexDecomposed2() {}
	virtual ISimplexIterator2* decompose(IStackAllocator& alloc) const = 0;
	/** @todo refine by iterator pattern. */
};

////////////////////////
#include "IBoundary2.h"

class SimplexVertex2;

class SimplexEdge2 : public ILinearEdge2
{
public:
	SimplexEdge2(const Simplex2& simplex)
		: simplex_(&simplex)
	{
	}
	virtual const Vector2 normal() const;
	const Vector2 tangent() const;

	virtual const Vector2 startPoint() const;
	virtual const Vector2 endPoint() const;
	virtual const Vector2 startNormal() const;
	virtual const Vector2 endNormal() const;

	IVertexIterator2* segmentate(Scalar tolerance, IStackAllocator& stack) const;

private:
	const Simplex2* simplex_;
};
